/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.ncsu.csc573.project1.util;
import edu.ncsu.csc573.project1.util.Constants.Status;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
/**
 *
 * @author svpendse1
 */
public class PPResponse {
    private String version;
    private Status status;
    private String data;
    private HeaderField dateField, osField, lastModifiedField;
    private HeaderField contentLengthField, contentTypeField;

    public HeaderField getContentLengthField() {
        return contentLengthField;
    }

    public void setContentLengthField(HeaderField contentLengthField) {
        this.contentLengthField = contentLengthField;
    }

    public HeaderField getContentTypeField() {
        return contentTypeField;
    }

    public void setContentTypeField(HeaderField contentTypeField) {
        this.contentTypeField = contentTypeField;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public HeaderField getDateField() {
        return dateField;
    }

    public void setDateField(HeaderField dateField) {
        this.dateField = dateField;
    }

    public HeaderField getLastModifiedField() {
        return lastModifiedField;
    }

    public void setLastModifiedField(HeaderField lastModifiedField) {
        this.lastModifiedField = lastModifiedField;
    }

    public HeaderField getOsField() {
        return osField;
    }

    public void setOsField(HeaderField osField) {
        this.osField = osField;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    
    public static class PPResponseBuilder {

        String version;
        Status status;
        HeaderField dateField, osField, lastModifiedField;
        HeaderField contentLengthField, contentTypeField;
        String data;
        
        public PPResponseBuilder() {
            
        }

        public PPResponseBuilder version(String version) {
            this.version = version;
            return this;
        }

        public PPResponseBuilder status(Status status) {
            this.status = status;
            return this;
        }
       
        public PPResponseBuilder dateField(HeaderField field) {
            this.dateField = field;
            return this;
        }

        public PPResponseBuilder osField(HeaderField field) {
            this.osField = field;
            return this;
        }

        public PPResponseBuilder lastModifiedField(HeaderField field) {
            this.lastModifiedField = field;
            return this;
        }

        public PPResponseBuilder contentLengthField(HeaderField field) {
            this.contentLengthField = field;
            return this;
        }

        public PPResponseBuilder contentTypeField(HeaderField field) {
            this.contentTypeField = field;
            return this;
        }

        public PPResponseBuilder data(String data) {
            this.data = data;
            return this;
        }
        
        public PPResponse build() {
            return new PPResponse(this);
        }

    }
    
    public PPResponse(PPResponseBuilder builder) {
        this.version = builder.version;
        this.status = builder.status;
        this.dateField = builder.dateField;
        this.osField = builder.osField;
        this.lastModifiedField = builder.lastModifiedField;
        this.contentLengthField = builder.contentLengthField;
        this.contentTypeField = builder.contentTypeField;
        this.data = builder.data;
    }

    //Return the string in the form of a string message consistent with the 
    //project description.
    public String getResponseMessage() {
        StringBuilder output = new StringBuilder();

        //Line 1
        output.append(version);
        output.append(" ");
        output.append(status.getCode());
        output.append(" ");
        output.append(status.getPhrase());
        output.append("\r\n");
        
        //Line 2
        output.append("Date: ");
        output.append(dateField.getValue());
        output.append("\r\n");

        //Line 3
        output.append("OS: ");
        output.append(osField.getValue());
        output.append("\r\n");

        if (status == Status.OK) {
            //Line 4
            output.append("Last-Modified: ");
            output.append(lastModifiedField.getValue());
            output.append("\r\n");
        
            //Line 5
            output.append("Content-Length: ");
            output.append(contentLengthField.getValue());
            output.append("\r\n");

            //Line 6
            output.append("Content-Type: ");
            output.append(contentTypeField.getValue());
            output.append("\r\n");

            //Line 7
            output.append(data);
        }

        return output.toString();
    }   

    //Parse an object of type PPResponse from an input string
    public static PPResponse parseFromString(String input) {
        PPResponse output = null;
        try {
            Scanner scanner = new Scanner(input);

            String version = scanner.next();

            if (! version.equals(Constants.kVersion)) {
                System.out.println("Incompatible version " + version);
                return null;
            }
            
            int code = scanner.nextInt();
            String phrase = scanner.nextLine().trim();

            Status status = Status.constructFromPhraseAndCode(phrase, code);

            if (status == null) {
                throw new Exception("Unknown status code : " + phrase + " " + code);
            }
            
            scanner.skip("Date: ");
            String date = scanner.nextLine();

            scanner.skip("OS: ");
            String os = scanner.nextLine();

            if (status == Status.OK) {
                scanner.skip("Last-Modified: ");
                String lastModified = scanner.nextLine();

                scanner.skip("Content-Length: ");
                String contentLength = scanner.nextLine();

                scanner.skip("Content-Type: ");
                String contentType = scanner.nextLine();
            
                String data = "";
                while (scanner.hasNextLine()) {
                    data += scanner.nextLine() +"\n";
                }
                output = new PPResponse.PPResponseBuilder().contentLengthField(new HeaderField("Content-Length", contentLength)).contentTypeField(new HeaderField("Content-Type", contentType)).data(data).dateField(new HeaderField("Date", date)).lastModifiedField(new HeaderField("Last-Modified", lastModified)).osField(new HeaderField("OS", os)).status(status).version(version).build();
            } else {
                output = new PPResponse.PPResponseBuilder().version(version).dateField(new HeaderField("Date", date)).osField(new HeaderField("OS", os)).status(status).build();
            }
            return output;
        } catch (Exception e) {
            System.out.println("Bad response");
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String data = "";
        try {
            BufferedReader buf = new BufferedReader(new InputStreamReader(new FileInputStream(new File("resources/rfc/rfc1001.txt"))));
            String input;
            while ((input = buf.readLine()) != null) {
                data += input +"\n";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        PPResponse response = new PPResponse.PPResponseBuilder().contentLengthField(new HeaderField("Content-Length", "length")).contentTypeField(new HeaderField("Content-Type", "type")).data(data).dateField(new HeaderField("Date", "some silly date")).lastModifiedField(new HeaderField("Last-Modified", "modified")).osField(new HeaderField("OS", "os")).status(Status.OK).version("version").build();

        System.out.println(response.getResponseMessage().length());
        PPResponse.parseFromString(response.getResponseMessage());

        System.out.println(PPResponse.parseFromString(response.getResponseMessage()).getResponseMessage().length());
    }
}
